package com.tsfyun.scm.service.impl.storage;

import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.tsfyun.common.base.constant.CacheConstant;
import com.tsfyun.common.base.enums.WarehouseTypeEnum;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.extension.OrderItem;
import com.tsfyun.common.base.util.TsfPreconditions;
import com.tsfyun.scm.dto.storage.WarehouseDTO;
import com.tsfyun.scm.dto.storage.WarehouseQTO;
import com.tsfyun.scm.entity.storage.Warehouse;
import com.tsfyun.scm.mapper.storage.WarehouseMapper;
import com.tsfyun.scm.service.storage.IWarehouseService;
import com.tsfyun.common.base.extension.ServiceImpl;
import com.tsfyun.scm.util.TsfWeekendSqls;
import com.tsfyun.scm.vo.storage.WarehouseVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 仓库 服务实现类
 * </p>
 *

 * @since 2020-03-31
 */
@Service
public class WarehouseServiceImpl extends ServiceImpl<Warehouse> implements IWarehouseService {

    @Autowired
    private WarehouseMapper warehouseMapper;

    @CacheEvict(value = CacheConstant.WAREHOUSE_DETAIL,allEntries = true,beforeInvocation = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(WarehouseDTO dto) {
        Warehouse warehouse = beanMapper.map(dto,Warehouse.class);
        warehouse.setDisabled(Boolean.FALSE);
        try {
            super.saveNonNull(warehouse);
        } catch (DuplicateKeyException e) {
            if(e.getMessage().contains("uni_code")) {
                throw new ServiceException(String.format("已经存在编码为：%s的仓库",dto.getCode()));
            } else {
                throw new ServiceException("数据已经存在");
            }
        }
    }

    @CacheEvict(value = CacheConstant.WAREHOUSE_DETAIL,allEntries = true,beforeInvocation = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(WarehouseDTO dto) {
        Warehouse warehouse = super.getById(dto.getId());
        TsfPreconditions.checkArgument(Objects.nonNull(warehouse),new ServiceException("仓库信息不存在"));
        warehouse.setCode(dto.getCode());
        warehouse.setName(dto.getName());
        warehouse.setCompanyName(dto.getCompanyName());
        warehouse.setAddress(dto.getAddress());
        warehouse.setAddressEn(dto.getAddressEn());
        warehouse.setLinkPerson(dto.getLinkPerson());
        warehouse.setLinkTel(dto.getLinkTel());
        warehouse.setNameEn(dto.getNameEn());
        warehouse.setMemo(dto.getMemo());
        warehouse.setIsSelfMention(dto.getIsSelfMention());
        warehouse.setWarehouseType(dto.getWarehouseType());
        try {
            super.updateById(warehouse);
        } catch (DuplicateKeyException e) {
            if(e.getMessage().contains("uni_code")) {
                throw new ServiceException(String.format("已经存在编码为：%s的仓库",dto.getCode()));
            } else {
                throw new ServiceException("数据已经存在");
            }
        }
    }

    @Override
    public PageInfo<Warehouse> page(WarehouseQTO qto) {
        TsfWeekendSqls sqls = TsfWeekendSqls.<Warehouse>custom()
                .andLike(true,Warehouse::getName,qto.getName())
                .andLike(true,Warehouse::getCode,qto.getCode())
                .andEqualTo(true,Warehouse::getWarehouseType,qto.getWarehouseType())
                .andEqualTo(true,Warehouse::getDisabled,qto.getDisabled());
        PageInfo<Warehouse> pageInfo = super.pageList(qto.getPage(),qto.getLimit(),sqls, Lists.newArrayList(OrderItem.desc("dateUpdated")));
        return pageInfo;
    }

    @CacheEvict(value = CacheConstant.WAREHOUSE_DETAIL,allEntries = true,beforeInvocation = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(Long id) {
        Warehouse warehouse = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(warehouse),new ServiceException("仓库信息不存在"));
        try {
            super.removeById(id);
        } catch (DataIntegrityViolationException e) {
            throw new ServiceException("该仓库存在关联性数据，不允许删除");
        }
    }

    @Override
    public List<WarehouseVO> allList(WarehouseQTO dto) {
        TsfWeekendSqls wheres = TsfWeekendSqls.<Warehouse>custom().andEqualTo(true,Warehouse::getWarehouseType,dto.getWarehouseType())
                .andEqualTo(false,Warehouse::getDisabled,Boolean.FALSE);
        Example example = Example.builder(Warehouse.class).where(wheres).build();
        example.setOrderByClause("date_updated desc");
        return beanMapper.mapAsList(warehouseMapper.selectByExample(example),WarehouseVO.class);
    }

    @CacheEvict(value = CacheConstant.WAREHOUSE_DETAIL,allEntries = true,beforeInvocation = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateDisabled(Long id, Boolean disabled) {
        Warehouse warehouse = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(warehouse),new ServiceException("仓库信息不存在"));

        Warehouse update = new Warehouse();
        update.setDisabled(disabled);
        warehouseMapper.updateByExampleSelective(update, Example.builder(Warehouse.class).where(
                TsfWeekendSqls.<Warehouse>custom().andEqualTo(false,Warehouse::getId, id)).build()
        );
    }

    @Cacheable(value = CacheConstant.WAREHOUSE_DETAIL,key = "#id",unless="#result == null")
    @Override
    public WarehouseVO detail(Long id) {
        Warehouse warehouse = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(warehouse),new ServiceException("仓库信息不存在"));
        return beanMapper.map(warehouse,WarehouseVO.class);
    }

    @Override
    public List<WarehouseVO> domesticSelfMentionWarehouses() {
        TsfWeekendSqls wheres = TsfWeekendSqls.<Warehouse>custom().andEqualTo(false,Warehouse::getWarehouseType,WarehouseTypeEnum.DOMESTIC.getCode())
                .andEqualTo(false,Warehouse::getDisabled,Boolean.FALSE)
                .andEqualTo(false,Warehouse::getIsSelfMention,Boolean.TRUE);
        Example example = Example.builder(Warehouse.class).where(wheres).build();
        example.setOrderByClause("date_updated desc");
        return beanMapper.mapAsList(warehouseMapper.selectByExample(example),WarehouseVO.class);
    }

    @Override
    public Warehouse getByCode(String code) {
        Warehouse condition = new Warehouse();
        condition.setCode(code);
        return super.getOne(condition);
    }

    @Override
    public List<WarehouseVO> allEnableWarehouses(WarehouseQTO qto) {
        TsfWeekendSqls wheres = TsfWeekendSqls.<Warehouse>custom()
                .andEqualTo(false,Warehouse::getDisabled,Boolean.FALSE)
                .andEqualTo(true,Warehouse::getWarehouseType,qto.getWarehouseType())
                .andEqualTo(true,Warehouse::getIsSelfMention,qto.getIsSelfMention());
        Example example = Example.builder(Warehouse.class).where(wheres).build();
        example.setOrderByClause("warehouse_type desc,date_updated desc");
        return beanMapper.mapAsList(warehouseMapper.selectByExample(example),WarehouseVO.class);
    }
}
